/**
 * [debounce description]
 * @param  {Function} fn        [description]
 * @param  {[number]}   delay     [延迟时间]
 * @param  {[Boolean]}   immediate [是否立即执行]
 * @return {[type]}             [description]
 * @author zhangguanggui 2018-07-31
 */
function debouce(fn, delay, immediate) {
    let timer;
    return function() {
        const context = this;
        const args = arguments;
        if (timer) {
            clearTimeout(timer);
        }
        const callNow = immediate && !timer;

        if (callNow) {
            fn.apply(context, args);
        }

        timer = setTimeout(() => {
            fn.apply(context, args);
            timer = null;
        }, delay);
    }

}

/*
  // 第二种写法
 function debouce(fn, delay, immediate) {
    let timer;
    return function() {
        const context = this;
        const args = arguments;
        if (timer) {
            clearTimeout(timer);
        }
        if (immediate) {
            const callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
                fn.apply(context, args); // 此处不调用 只会执行一次
            }, delay);
            // 第一次执行
            if (callNow) {
                fn.apply(context, args);
            }
        } else {
            timer = setTimeout(() => fn.apply(context, args), delay);
        }
    }

}
*/




/**
 * [throttle 节流] 
 * @param  {Function} fn    [description]
 * @param  {[type]}   delay [description]
 * @return {[type]}         [description]
 * @author zhangguanggui 2018-07-31
 */
/* 时间戳方法
function throttle(fn, delay) {
    let start = Date.now();
    return function() {
        const context = this;
        const args = arguments;
        const now = Date.now();
        if (now - start >= delay) {
            start = now;
            fn.apply(context, args);
        }
    }
}
*/

/*
 **定时器方法**

function throttle(fn, delay) {
    let timer = null;
    return function() {
        const context = this;
        const args = arguments;
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(context, args);
                clearTimeout(timer);
                timer = null;
            }, delay);
        }
    }

}
*/

/*综合时间戳与定时器方法*/
function throttle(fn, delay) {
    let timer = null;
    let start = Date.now();
    return function() {
        const now = Date.now();
        const remain = delay - (now - start);
        const context = this;
        const args = arguments;
        clearTimeout(timer);
        if (remain <= 0) {
            fn.apply(context, args);
            start = Date.now();
        } else {
            timer = setTimeout(() => fn.apply(context, args), remain);
        }
    }
}



// function test(e) {
//     console.log('test');
//     console.log(e);
// }
// window.onmousemove = throttle(test, 1500, true);